package com.yulan.bankback.service.bank.impl;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yulan.bankback.entity.model.admin.IllegalTrading;
import com.yulan.bankback.entity.model.admin.ViolationUser;
import com.yulan.bankback.entity.model.bank.BankUser;
import com.yulan.bankback.entity.model.bank.UserCapitalFlow;
import com.yulan.bankback.entity.model.bank.UserMsg;
import com.yulan.bankback.entity.dto.bank.ChatDto;
import com.yulan.bankback.entity.dto.bank.SystemMsgDto;
import com.yulan.bankback.entity.dto.bank.UserMsgDto;
import com.yulan.bankback.entity.vo.MsgVo;
import com.yulan.bankback.log.Logger;
import com.yulan.bankback.mapper.admin.IllegalTradingMapper;
import com.yulan.bankback.mapper.admin.ViolationUserMapper;
import com.yulan.bankback.mapper.bank.BankUserMapper;
import com.yulan.bankback.mapper.bank.UserCapitalFlowMapper;
import com.yulan.bankback.mapper.bank.UserMsgMapper;
import com.yulan.bankback.service.bank.MsgService;
import com.yulan.bankback.util.MD5Util;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@Service
public class MsgServiceImpl extends ServiceImpl<UserMsgMapper, UserMsg>
        implements MsgService {


    private static final SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    private static final SimpleDateFormat formatter2 = new SimpleDateFormat("yyyy-MM-dd");


    @Resource
    private UserMsgMapper userMsgMapper;

    @Resource
    private BankUserMapper bankUserMapper;

    @Resource
    private UserCapitalFlowMapper userCapitalFlowMapper;

    @Resource
    private IllegalTradingMapper illegalTradingMapper;

    @Resource
    private ViolationUserMapper violationUserMapper;

    @Autowired
    private Logger logger;

    @Override
    public MsgVo getMsgVo(String uid) {
        BankUser user = bankUserMapper.selectById(uid);
        if(user == null) return null;
        MsgVo msgVo = new MsgVo();

        msgVo.setFreeMoney(user.getMoney());

        //获取系统通知
        List<UserMsg> systemMsg = userMsgMapper.selectList(
                new QueryWrapper<UserMsg>()
                        .eq("type", "system-msg")
                        .eq("dest_uid", uid));
        List<SystemMsgDto> systemMsgDtos = systemMsg.stream().map(this::convertUserMsg2SystemMsg).collect(Collectors.toList());

        msgVo.setSystemMsg(systemMsgDtos);

        //获取所有好友聊天信息
        List<UserMsg> friendMsg = userMsgMapper.getAllChat(uid);

        HashSet<String> friends = new HashSet<>();

        friendMsg.forEach(item ->{
            friends.add(item.getSrcUid());
            friends.add(item.getDestUid());
        });

        friends.remove(uid);

        List<ChatDto> chatDtos = new ArrayList<>();

        friends.forEach(id -> {
            ChatDto dto = new ChatDto();
            BankUser friend = bankUserMapper.selectById(id);
            dto.setFriendName(friend.getUserName());
            dto.setFriendUid(id);
            dto.setHeadImgUrl(friend.getHeadImgUrl());
            List<UserMsgDto> userMsgDtos = new ArrayList<>();
            AtomicInteger indexCounter = new AtomicInteger();
            friendMsg.forEach(item -> {
                UserMsgDto userMsgDto = new UserMsgDto();
                //如果不是该用户发的消息
                if(item.getSrcUid().equals(id)){
                    userMsgDto.setMsgIndex(indexCounter.getAndIncrement());
                    userMsgDto.setMsgId(item.getMsgId());
                    userMsgDto.setName(friend.getUserName());
                    userMsgDto.setMsg(item.getMsg());
                    userMsgDto.setType(item.getType());
                    userMsgDto.setDate(formatter.format(item.getMsgDate()));
                    userMsgDto.setIndex("left");
                //如果是该用户收到消息
                }else if(item.getDestUid().equals(id)){
                    userMsgDto.setMsgIndex(indexCounter.getAndIncrement());
                    userMsgDto.setMsgId(item.getMsgId());
                    userMsgDto.setName(friend.getUserName());
                    userMsgDto.setMsg(item.getMsg());
                    userMsgDto.setType(item.getType());
                    userMsgDto.setDate(formatter.format(item.getMsgDate()));
                    userMsgDto.setIndex("right");
                }else{
                    return;
                }
                userMsgDtos.add(userMsgDto);
            });
            indexCounter.set(0);
            dto.setMsg(userMsgDtos);
            UserMsgDto lastMsg = userMsgDtos.get(userMsgDtos.size() - 1);
            if(lastMsg.getType().equals("transfer-not-get")){
                dto.setLastMsg("[转账]  " + lastMsg.getMsg() + " 元");
                dto.setLastMsgType(lastMsg.getType());
            }else if(lastMsg.getMsg().length() > 10){
                dto.setLastMsg(lastMsg.getMsg() + "......");
                dto.setLastMsgType(lastMsg.getType());
            }else{
                dto.setLastMsg(lastMsg.getMsg());
                dto.setLastMsgType(lastMsg.getType());
            }
            chatDtos.add(dto);
        });

        System.out.println("msgVo: " + chatDtos);
        msgVo.setFriendMsg(chatDtos);


        return msgVo;
    }

    @Override
    public String addMsg(String srcUid, String destUid, String msg, String type, String msgDate) throws ParseException {
        int count = userMsgMapper.insert(new UserMsg(srcUid, destUid, msg, formatter.parse(msgDate), type));
        return count == 1 ? "success" : "发送失败";
    }

    @Override
    public String getMoneyMsg(String uid, String msgId) {
        UserMsg msg = userMsgMapper.selectById(msgId);
        BankUser user = bankUserMapper.selectById(uid);
        if(msg == null)
            return "该消息已被清除，请重新加载";
        if(user == null)
            return "不存在该用户";

        user.setMoney(user.getMoney() + Double.valueOf(msg.getMsg()));
        msg.setType("transfer-get");
        userMsgMapper.updateById(msg);
        bankUserMapper.updateById(user);

        return "success";
    }

    @Override
    public String sendMoney(String srcUid, String destUid, String payPassword,
                            String msg, String msgDate) throws ParseException {
        BankUser user = bankUserMapper.selectById(srcUid);
        BankUser destUser = bankUserMapper.selectById(destUid);
        if(!StringUtils.equals(user.getPayPassword(), MD5Util.encoderByMd5(payPassword))){
            return "支付密码错误";
        }
        if(user.getMoney() < Double.valueOf(msg))
            return "余额不足";
        user.setMoney(user.getMoney() - Double.valueOf(msg));
        bankUserMapper.updateById(user);
        int count = userMsgMapper.insert(new UserMsg(srcUid, destUid, msg, formatter.parse(msgDate), "transfer-not-get"));

        double money = Double.valueOf(msg);
        userCapitalFlowMapper.insert(new UserCapitalFlow(srcUid, money,
                "expend", new Date(), "", new Date(), "转账给其他用户("+ user.getPhone() + ")", 0));
        userCapitalFlowMapper.insert(new UserCapitalFlow(destUser.getId(), money,
                "income", new Date(), "", new Date(), "接收其他用户(" + destUser.getPhone() + ")的转账", 0));

        //如果是违规用户
        if(violationUserMapper.selectById(destUser.getId()) != null){
            illegalTradingMapper.insert(new IllegalTrading(UUID.randomUUID().toString().replaceAll("-",""),
                    srcUid, user.getUserName(), new Date(),"", "与违规用户发生交易",money, 0));
        }


        logger.logMoneyFlow(srcUid, destUser.getId(), String.valueOf(money), "chat_transfer");
        return count == 1 ? "success" + "_" + user.getMoney() : "发送失败";
    }


    private SystemMsgDto convertUserMsg2SystemMsg(UserMsg userMsg){
        SystemMsgDto dto = new SystemMsgDto();
        dto.setContent(userMsg.getMsg());
        dto.setDate(formatter.format(userMsg.getMsgDate()));
        return dto;
    }
}















